#!/bin/bash

# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

echo "Configuring for backchannel and test network devices"

testif=eth_test
wlanifs=wlan1,wlan2,managed0,managed1
modemif=pseudomodem0p
test_devices="${testif},${wlanifs},${modemif}"

# Prevent shill from taking control of the backchannel and test network devices.
ORIG_CONF=${ROOT_FS_DIR}/etc/init/shill.conf
TEMP_CONF=${ORIG_CONF}.tmp
sed -e "s@SHILL_TEST_DEVICES=\"\"@SHILL_TEST_DEVICES=\"${test_devices}\"@" \
    -e "s@SHILL_ACCEPT_HOSTNAME_FROM=@SHILL_ACCEPT_HOSTNAME_FROM=\"pseudoethernet0\"@" \
    ${ORIG_CONF} > ${TEMP_CONF}
mv -f ${TEMP_CONF} ${ORIG_CONF}

# Arrange to run dhclient on the backchannel device but without
# installing the default route, and stashing said route away for later
# installation as a host route.
cat > ${ROOT_FS_DIR}/etc/udev/rules.d/50-backchannel-network.rules <<EOF
KERNEL=="eth*", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/sbin/backchannel-setup %k"
KERNEL=="${testif}", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="kill \$(cat /var/run/dhclient-%k.pid)"
EOF

cat > ${ROOT_FS_DIR}/sbin/backchannel-setup <<EOF
#!/bin/sh

testif=${testif}

if [ ! -f /mnt/stateful_partition/etc/enable_backchannel_network ]; then
    # This mechanism has to be explicitly enabled on the device.
    exit
fi

if [ -f /var/run/dhclient-\${testif}.pid ]; then
    # Something else is already going on - perhaps a second
    # USB Ethernet device has been inserted. Let's not mess with it.
    exit
fi

if [ "\$1" != "\${testif}" ]; then
    initctl stop shill
    # \$1 is the current name of the backchannel device. Swap it with testif.
    if ifconfig \${testif} > /dev/null 2>&1; then
        orig_mac=\$(ifconfig \${testif} | awk '/HWaddr/ {print \$5}')
        ifconfig \${testif} down # must be down for nameif to work
        nameif eth_tmp \${orig_mac}
    fi
    bdev_mac=\$(ifconfig \$1 | awk '/HWaddr/ {print \$5}')
    ifconfig \$1 down # must be down for nameif to work
    nameif \${testif} \${bdev_mac}
    if [ -n "\${orig_mac}" ]; then
        nameif \$1 \${orig_mac}
    fi
    initctl start shill
fi

# Bring up the backchannel interface
dhclient -q -pf /var/run/dhclient-\${testif}.pid \\
            -lf /var/run/dhclient-\${testif}.leases \\
            -cf /etc/dhclient-backchannel.conf \\
            -sf /sbin/dhclient-backchannel-script \\
         \${testif}
EOF

chmod +x ${ROOT_FS_DIR}/sbin/backchannel-setup

cat > ${ROOT_FS_DIR}/etc/dhclient-backchannel.conf <<EOF
request subnet-mask, broadcast-address, routers;
EOF

cat > ${ROOT_FS_DIR}/sbin/dhclient-backchannel-script <<EOF
#!/bin/sh

if [ -n "\$new_broadcast_address" ]; then
    new_broadcast_arg="broadcast \$new_broadcast_address"
fi
if [ -n "\$new_subnet_mask" ]; then
    new_subnet_arg="netmask \$new_subnet_mask"
fi


case "\$reason" in
    MEDIUM|ARPCHECK|ARPSEND)
        # Do nothing
        ;;
    PREINIT)
        # The DHCP client is requesting that an interface be
        # configured as required in order to send packets prior to
        # receiving an actual address. - dhclient-script(8)

        ifconfig \$interface inet 0 up

        # We need to give the kernel some time to get the interface up.
        sleep 1
        ;;

    BOUND|RENEW|REBIND|REBOOT|TIMEOUT)
        if [ -n "\$old_ip_address" -a \
             "\$old_ip_address" != "\$new_ip_address" ]; then
            # IP address changed. Bringing down the interface will delete all routes,
            # and clear the ARP cache.
            ifconfig \$interface inet 0

        fi

        if [ -z "\$old_ip_address" -o "\$old_ip_address" != "\$new_ip_address" -o \
            "\$reason" = "BOUND" -o "\$reason" = "REBOOT" ]; then

            ifconfig \$interface inet \$new_ip_address \$new_subnet_arg \
                \$new_broadcast_arg \$mtu_arg

            # Since this script is for the backchannel testing interface,
            # we don't set the default route from here, but we do stash
            # it for possible later use in setting up a host route.
            cp /dev/null /var/run/dhclient-\${interface}.routers
            for router in \$new_routers; do
                echo \$router >> /var/run/dhclient-\${interface}.routers
            done
        fi
        ;;

    EXPIRE|FAIL|RELEASE|STOP)
        if [ -n "\$old_ip_address" ]; then
            # Shut down interface, which will delete routes and clear arp cache.
            ifconfig \$interface inet 0
        fi
        ;;
esac
EOF

chmod +x ${ROOT_FS_DIR}/sbin/dhclient-backchannel-script
